#include "StdAfx.h"
#include "CarAgent.h"
#include "Env.h"

CCarAgent::CCarAgent(int id, CNode* node, EAgentType type) 
    : CAgent(id, type, node)
{
}

CCarAgent::CCarAgent(int id, CPath* path) 
    : CAgent(id, ETYPE_CAR, path->GetSource())
{
    SetPath(path);
}

CCarAgent::~CCarAgent(void)
{
}

void CCarAgent::SetPath(CPath* path)
{    
    m_path = path;
    m_itPath = path->GetIterator();
}

bool CCarAgent::Step(CEnv* env, int ms)
{
    bool ret = __super::Step(env, ms);
    
    if (m_status != ESTATUS_TRANSIT)
    {
        m_action = CSysTime::Now();
        m_next = GetNextNode();

        if (m_next == NULL)
            return false;

        m_status = ESTATUS_TRANSIT;
    }
    else
    {    
        if (m_next == NULL)
            return false;

        if (m_pt == m_next->m_pt)
        {
            m_status = ESTATUS_STOPPED;
            m_node = m_next;
        }
    }

    UpdatePosition(env->GetAgentSpeed(), ms);

    return ret;
}

CNode* CCarAgent::GetNextNode()
{
    if (m_path && m_node != m_path->GetDestination())
    {
        CNode* node = *m_itPath++;
        if (node == m_node)
            node = *m_itPath++;

        return node;
    }
    else
    {
        return NULL;
    }
}

void CCarAgent::UpdatePosition(int pps, int ms)
{

    int pix = ((double)(GetTrafficModifier() * pps)/1000) * ms;
    
    //CSysTime diff = CSysTime::Now() - m_action;
    //int pix = diff.GetSeconds() * PPS;

    // Get dx and dy, and with the right sign.
    int dx, dy;
    if (m_next->m_pt.x - m_node->m_pt.x > 0)
        dx = pix;
    else if (m_next->m_pt.x - m_node->m_pt.x < 0)
        dx = -1 * pix;
    else
        dx = 0;

    if (m_next->m_pt.y - m_node->m_pt.y > 0)
        dy = pix;
    else if (m_next->m_pt.y - m_node->m_pt.y < 0)
        dy = -1 * pix;
    else
        dy = 0;

    m_pt.x += /*m_node->m_pt.x*/ + dx;
    m_pt.y += /*m_node->m_pt.y*/ + dy;

    // Correct overshoot
    if (dx > 0 && m_pt.x > m_next->m_pt.x)
        m_pt.x = m_next->m_pt.x;
    else if (dx < 0 && m_pt.x < m_next->m_pt.x)
        m_pt.x = m_next->m_pt.x;

    if (dy > 0 && m_pt.y > m_next->m_pt.y)
        m_pt.y = m_next->m_pt.y;
    else if (dy < 0 && m_pt.y < m_next->m_pt.y)
        m_pt.y = m_next->m_pt.y;
}

CNodePtrVec* CCarAgent::GetPathVector()
{
    if (m_path)
        return m_path->GetPath();
    else
        return NULL;
}

double CCarAgent::GetTrafficModifier()
{

    if (m_next->m_pt.x - m_node->m_pt.x > 0)
    {
        // Moving East
        return GetModifier(m_node->m_east, m_node->m_trafE);
    } 
    else if (m_next->m_pt.x - m_node->m_pt.x < 0)
    {
        // Moving West
        return GetModifier(m_node->m_west, m_node->m_trafW);
    }

    if (m_next->m_pt.y - m_node->m_pt.y > 0)
    {
        // Moving South
        return GetModifier(m_node->m_south, m_node->m_trafS);
    } 
    else if (m_next->m_pt.y - m_node->m_pt.y < 0)
    {
        // Moving North
        return GetModifier(m_node->m_north, m_node->m_trafN);
    }
}

double CCarAgent::GetModifier(CNode* to, int traffic)
{
    if (traffic == 0)
        return 0;

    int distance = m_node->GetDistance(to);
    double capacity = (double) distance / 20;

    double mod = capacity / traffic;
    if (mod > 1.0) mod = 1.0;
    return mod;
}